<?php
/**
 * 扩展MongoDB类使用
 * @author QQ:249828165
 */

class Mdb
{

    private $ins = array();
    //单例
    private static $instance = array();


    private function __construct($name)
    {
        require_once dirname(__FILE__).'/DbAgent.php';
        $dbConn = DbAgent::getInstance();
        if ($dbConn->config['db'] == "mysql") {
            exit('数据库类型被配置为mysql，请检查！');
        }
        $this->ins = $dbConn;
    }

    /**
     * 单例模式
     * @param $name
     */
    public static function getInstance($name = "main")
    {
        if (empty(self::$instance[$name])) {
            self::$instance[$name] = new self($name);
        }
        return self::$instance[$name];
    }

    /**
     * 类似mysql的sum功能
     * @param $collection 表名
     * @param $wheres 条件
     * @param $key sum哪个字段
     * @param $group 指定group by的字段
     * @return int
     */
    public function sum($collection, $wheres, $key, $group)
    {
        $initial = array("sum_$key"=>0 );
        $reduce = "function(obj, prev) { if(obj.{$key}){prev.sum_{$key} += obj.{$key};} }";
        $db = $this->ins->getDb()->$collection;
        $data =$db-> group(array($group=>true), $initial, $reduce, $wheres);
        foreach($data as $v)
        {
            return (int)$v[0]["sum_$key"];
        }
        return 0;
	}

    public function count($collection, $wheres)
    {
		return $this->ins->count_mongodb($collection, $wheres);
	}

    /**
     * 取记录, 返回结果集
     *
     * @param string $collection    collection
     * @param array $wheres         条件        例：array("x" => array('$gt' => 80))
     * @param array $fields         指定域(null为所有, array("id"=>true))
     * @param array $orderby        排序 array('id'=>1) ASC， array('id'=>-1) DESC
     * @return array
     *
     * Less than.                            const LT = '$lt'; <
     * Less than or equal to.                const LTE = '$lte'; <=
     * Greater than.                        const GT = '$gt';  >
     * Greater than or equal to.            const GTE = '$gte'; >=
     * Checks for a field in an object.        const IN = '$in';
     * Not equal.                            const NE = '$ne';
     * Sort ascending.                        const ASC = 1;
     * Sort descending.                        const DESC = -1;
     */
    public function getAll($collection, $wheres, $fields=array(), $orderby=null, $limit = null, $returnId = false)
    {
        return $this->ins->fetchRow_mongodb($collection, $wheres, $fields, $orderby, $limit, $returnId);
    }

    /**
     * 取一条记录
     *
     * @param string $collection    collection
     * @param array $wheres  例：array("x" => array('$gt' => 80))注意where内容是区分数字与字符串的
     * @param array $fields         指定域(null为所有, array("id"=>true))
     * @param array $orderby        排序
     * @return array
     *
     * Less than.                            const LT = '$lt';
     * Less than or equal to.                const LTE = '$lte';
     * Greater than.                        const GT = '$gt';
     * Greater than or equal to.            const GTE = '$gte';
     * Checks for a field in an object.        const IN = '$in';
     * Not equal.                            const NE = '$ne';
     * Sort ascending.                        const ASC = 1;
     * Sort descending.                        const DESC = -1;
     */
    public function getRow($collection, $wheres, $fields=array(), $orderby=array(), $returnId = false)
    {
        $rows = $this->getAll($collection, $wheres, $fields, $orderby, 1, $returnId);
        if($rows)
            foreach($rows as $row)
                return $row;
        return array();
    }

    public function getOne($collection, $wheres, $fields=array(), $orderby=array(), $returnId = false)
    {
        $rows = $this->getRow($collection, $wheres, $fields, $orderby, $returnId);
        foreach($rows as $v)
            return $v;
        return null;
    }

    /**
     * 插入记录
     *
     * @param string $collection        collection
     * @param array  $fields_vals         域名_值            例：array("x" =>100,"y" => 20)
     * @return array
     */
    public function insert($collection, $key_vals)
    {
        return $this->ins->insert_mongodb($collection, $key_vals);
    }

    /**
     * 修改记录
     *
     * @param string $collection    collection
     * @param array $wheres             条件        例：array("x" => array('$gt' => 80))
     * @param array  $fields_vals         域名_值            例：array("x" =>100,"y" => 20)
     * @param array $options 选项                   例：array(’safe’=>true,’multiple’=>true)
     * safe 是否返回操作结果
    fsync 是否是直接影响到物理硬盘
    upsert 是否没有匹配数据就添加一条新的
    multiple 是否影响所有符合条件的记录，默认只影响一条
     * @return array
     *
     * Less than.                            const LT = '$lt';
     * Less than or equal to.                const LTE = '$lte';
     * Greater than.                        const GT = '$gt';
     * Greater than or equal to.            const GTE = '$gte';
     * Checks for a field in an object.        const IN = '$in';
     * Not equal.                            const NE = '$ne';
     * Sort ascending.                        const ASC = 1;
     * Sort descending.                        const DESC = -1;
     */
    public function update($collection, $wheres, $fields_vals, $options = array())
    {
        $data = $this->getAll($collection, $wheres, array(), array(), null, true);
        foreach($data as $val)
        {
            foreach($fields_vals as $k=>$v)
            {
                $val[$k] = $v;
            }
            $this->ins->update_mongodb($collection, array('_id'=>$val['_id']), $val, $options);
        }
        return true;
    }

    /**
     * 删除记录
     *
     * @param string $collection    collection
     * @param array $wheres             条件        例：array("x" => array('$gt' => 80))
     * @return array
     *
     * Less than.                            const LT = '$lt';
     * Less than or equal to.                const LTE = '$lte';
     * Greater than.                        const GT = '$gt';
     * Greater than or equal to.            const GTE = '$gte';
     * Checks for a field in an object.        const IN = '$in';
     * Not equal.                            const NE = '$ne';
     * Sort ascending.                        const ASC = 1;
     * Sort descending.                        const DESC = -1;
     */
    public function delete($collection, $wheres)
    {
        return $this->ins->delete_mongodb($collection, $wheres);
    }

    public function getAutoId($collection)
    {
        return $this->ins->getAutoId_mongodb($collection, "id");
    }

    /**
     * 分页
     *
     * @param string $collection    collection
     * @param int $curpage            当前页号
     * @param int $pagesize            页长
     * @param array $wheres         条件        例：array("x" => array('$gt' => 80))
     * @param array $fields         指定域(null为所有)
     * @param array $orderby        排序
     * @param string $url           分页url
     * @return array
     *
     * Less than.                            const LT = '$lt';
     * Less than or equal to.                const LTE = '$lte';
     * Greater than.                        const GT = '$gt';
     * Greater than or equal to.            const GTE = '$gte';
     * Checks for a field in an object.        const IN = '$in';
     * Not equal.                            const NE = '$ne';
     *
     * Sort ascending.                        const ASC = 1;
     * Sort descending.                        const DESC = -1;
     */
    public function getPage($collection, $url, $wheres=array(), $orderby=array(), $fields=array(), $pagesize=30, $returnId = false)
    {
        $page = isset($_REQUEST['page']) ? intval($_REQUEST['page']) : 1;
        return $this->ins->findpage_mongodb($collection, $page, $pagesize, $wheres, $fields, $orderby, $url, $returnId);
    }

}
